package com.xd.user.config;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.xd.common.base.ApiController;
import com.xd.common.model.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.PersistenceException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.transaction.UnexpectedRollbackException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.sql.SQLException;

/**
 * @author huboxin
 * @date 2020/11/5-15:56
 */
@Slf4j
@RestControllerAdvice
public class WebExceptionController extends ApiController {


    /**
     * 参数效验异常处理
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R myMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error("参数解析失败", e);
        if (null != e.getBindingResult()
                .getFieldError()
                && !ObjectUtil.isEmpty(e.getBindingResult()
                .getFieldError()
                .getDefaultMessage())) {
            return failed(e.getBindingResult()
                    .getFieldError()
                    .getDefaultMessage()
                    .length() <= 20 ? e.getBindingResult()
                    .getFieldError()
                    .getDefaultMessage() : "参数校验失败");
        }
        return failed("参数校验异常");
    }

    /**
     * 单参数 @NotNull @NotBlank @NotEmpty 效验异常处理
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public R handleConstraintViolationException(ConstraintViolationException e) {
        log.error("参数校验异常", e);
        if (null != e.getConstraintViolations() && !org.springframework.util.ObjectUtils.isEmpty(e.getConstraintViolations())) {
            String[] split = e.getMessage()
                    .split(",");
            String message = split[0].substring(e.getMessage()
                    .indexOf(":") + 1);
            return failed(message);
        }
        return failed("参数校验异常");
    }

    /**
     * 空指针异常
     */
    @ExceptionHandler(NullPointerException.class)
    public R nullPointerExceptionHandler(NullPointerException ex) {
        ex.printStackTrace();
        return failed("数据操作错误");
    }

    /**
     * sql操作异常
     */
    @ExceptionHandler(SQLException.class)
    public R SQLExceptionHandler(SQLException ex) {
        ex.printStackTrace();
        return failed("数据操作错误");
    }

    /**
     * 数据操作异常
     */
    @ExceptionHandler(PersistenceException.class)
    public R persistenceExceptionHandler(PersistenceException ex) {
        ex.printStackTrace();
        return failed("数据操作错误");
    }


    /**
     * 400 - Bad Request
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
        ex.printStackTrace();
        return failed("参数解析失败");
    }

    /**
     * 405 - Method Not Allowed
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) {
        ex.printStackTrace();
        return failed("数据操作错误");
    }

    /**
     * 415 - Unsupported Media Type
     */
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public R handleHttpMediaTypeNotSupportedException(Exception ex) {
        ex.printStackTrace();
        return failed("数据操作错误");
    }

    /**
     * 500 - Internal Server Error
     */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R handleException(Exception ex) {
        ex.printStackTrace();
        return failed("数据操作错误");
    }

    /**
     * 数据操作失败,触发事务
     */
    @ExceptionHandler(UnexpectedRollbackException.class)
    public R unexpectedRollbackException(UnexpectedRollbackException ex) {
        ex.printStackTrace();
        return failed("数据操作错误");
    }

}
